home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 January: Mac OS SDK / Dev.CD Jan 00 SDK2.toast / Development Kits / Hardware / Mac OS USB DDK v1.3f3 / Examples / MouseModule / MouseModule.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-08-20  |  18.6 KB  |  566 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        MouseModule.c
  3.  
  4.     Contains:    HID Module for USB Mouse
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1997-1999 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12.  
  13. /*
  14.     Notes to developers:
  15.     
  16.     1. The WatchDog functionality is *NOT* needed in your drivers.  It is part of an experiment to determine
  17.     if IntReads are ever dropped on the floor.  It was left in (but disabled) and checked into the 
  18.     projector database so that the coding effort wasn't lost.  We do not believe that IntReads are lost, so
  19.     your drivers should not need this WatchDog functionality.
  20.     
  21.     2. Apple reserves the right to do the following:
  22.         Release Mouse or Keyboard drivers that are vendor specific for Apple products
  23.         Release said mouse or keyboard drivers in binary form (but not necessarily in source form)
  24.         Prevent 3rd parties from writing generic drivers
  25.  
  26. */
  27.  
  28.  
  29. #include <Types.h>
  30. #include <Devices.h>
  31. #include <processes.h>
  32. #include <DriverServices.h>
  33. #include <USB.h>
  34. #include <LowMem.h>
  35.  
  36. #include "MouseModule.h"
  37.  
  38. #define    EnableWatchDog    0
  39. #define EnableRemoteWakeup 0
  40.  
  41. usbMousePBStruct myMousePB;
  42. usbMousePBStruct watchDogPB;
  43.  
  44. void InitParamBlock(USBReference theInterfaceRef, USBPB * paramblock)
  45. {
  46.     paramblock->usbReference = theInterfaceRef;
  47.     paramblock->pbVersion = kUSBCurrentPBVersion;
  48.     
  49.     paramblock->usb.cntl.WIndex = 0;             
  50.     paramblock->usb.cntl.WValue = 0;
  51.     
  52.     paramblock->usbBuffer = nil;        
  53.     paramblock->usbActCount = 0;
  54.     paramblock->usbReqCount = 0;
  55.     paramblock->usbFlags = 0;
  56.     paramblock->usbOther = 0;
  57.     
  58.     paramblock->usbStatus = noErr;
  59. }
  60.  
  61.  
  62.  
  63. Boolean immediateError(OSStatus err)
  64. {
  65.     return((err != kUSBPending) && (err != noErr) );
  66. }
  67.  
  68. void MouseInitiateTransaction(USBPB *pb)
  69. {
  70. usbMousePBStruct *pMousePB;
  71. OSStatus myErr;
  72.  
  73.     pMousePB = (usbMousePBStruct *)(pb);
  74.     pMousePB->transDepth++;
  75.     if (pMousePB->transDepth < 0)
  76.     {
  77.         USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": transDepth < 0 (initiation)", pMousePB->pb.usbRefcon );
  78.     }
  79.     
  80.     if (pMousePB->transDepth > 1)
  81.     {
  82.         USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": transDepth > 1 (initiation)", pMousePB->pb.usbRefcon );
  83.     }
  84.     
  85.     if (pMousePB->driverRemovalPending)
  86.     {
  87.         pMousePB->pb.usbRefcon = kReturnFromDriver;
  88.         return;
  89.     }
  90.  
  91.     switch(pMousePB->pb.usbRefcon & ~kRetryTransaction)
  92.     {
  93.         case kConfigureInterface:
  94.             InitParamBlock(pMousePB->interfaceRef, &pMousePB->pb);
  95.             
  96.             pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
  97.             pMousePB->pb.usbRefcon |= kCompletionPending;
  98.             
  99.             myErr = USBConfigureInterface( &pMousePB->pb );
  100.             if(immediateError(myErr))
  101.             {
  102.                 USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": kConfigureInterface - immediate error", myErr);
  103.                 pMousePB->pb.usbRefcon = kReturnFromDriver;
  104.             }
  105.             break;
  106.         
  107.         case kSetProtocol:
  108.             InitParamBlock(pMousePB->interfaceRef, &pMousePB->pb);
  109.             
  110.             pMousePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);            
  111.             pMousePB->pb.usb.cntl.BRequest = kHIDRqSetProtocol;
  112.             pMousePB->pb.usb.cntl.WValue = kHIDBootProtocolValue; 
  113.             pMousePB->pb.usb.cntl.WIndex = pMousePB->interfaceDescriptor.interfaceNumber;
  114.             
  115.             pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
  116.             pMousePB->pb.usbRefcon |= kCompletionPending;
  117.         
  118.             myErr = USBDeviceRequest(&pMousePB->pb);
  119.             if (immediateError(myErr))
  120.             {
  121.                 USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": kSetProtocol - immediate error", myErr);
  122.             }
  123.             break;
  124.             
  125.         case kSetIdleRequest:
  126.             USBExpertStatus(pMousePB->interfaceRef, kMouseModuleName": Do a SetIdle on non-Apple mice, as some 3rd party mice don't send reports on button up", pMousePB->pipeRef);
  127.             InitParamBlock(pMousePB->interfaceRef, &pMousePB->pb);
  128.             
  129.             pMousePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);            
  130.             
  131.             pMousePB->pb.usb.cntl.BRequest = kHIDRqSetIdle;
  132.             pMousePB->pb.usb.cntl.WValue = ((24/4)<<8);                 // force a read completion if idle for more than 24ms
  133.             pMousePB->pb.usb.cntl.WIndex = pMousePB->interfaceDescriptor.interfaceNumber;
  134.             
  135.             pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
  136.             pMousePB->pb.usbRefcon |= kCompletionPending;
  137.  
  138.             myErr = USBDeviceRequest(&pMousePB->pb);
  139.             if(immediateError(myErr))
  140.             {
  141.                 USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": kSetIdleRequest - immediate error", myErr);
  142.             }
  143.             break;
  144.  
  145. #if EnableRemoteWakeup
  146.         case kSetRemoteWakeup:
  147.             USBExpertStatusLevel(3, pMousePB->interfaceRef, kMouseModuleName": Set remote wakeup for mouse", pMousePB->pipeRef);
  148.             InitParamBlock(pMousePB->interfaceRef, &pMousePB->pb);
  149.             
  150.             pMousePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBDevice);            
  151.             
  152.             pMousePB->pb.usb.cntl.BRequest = kUSBRqSetFeature;
  153.             pMousePB->pb.usb.cntl.WValue = kUSBFeatureDeviceRemoteWakeup; 
  154.             pMousePB->pb.usb.cntl.WIndex = 0;
  155.             
  156.             pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
  157.             pMousePB->pb.usbRefcon |= kCompletionPending;
  158.  
  159.             myErr = USBDeviceRequest(&pMousePB->pb);
  160.             if(immediateError(myErr))
  161.             {
  162.                 USBExpertFatalError(pMousePB->interfaceRef, myErr, kMouseModuleName": set remote wakeup request - immediate error", myErr);
  163.             }
  164.             break;
  165. #endif
  166.  
  167.         case kFindPipe:
  168.             InitParamBlock(pMousePB->interfaceRef, &pMousePB->pb);
  169.             
  170.             pMousePB->pb.usbFlags = kUSBIn;
  171.             pMousePB->pb.usbClassType = kUSBInterrupt;
  172.             
  173.             pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
  174.             pMousePB->pb.usbRefcon |= kCompletionPending;
  175.         
  176.             myErr = USBFindNextPipe( &pMousePB->pb );
  177.             if((immediateError(myErr)) || (pMousePB->pb.usbBuffer == nil))
  178.             {
  179.                 USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": kFindPipe - immediate error", myErr);
  180.                 pMousePB->pb.usbRefcon = kReturnFromDriver;
  181.             }
  182.             
  183.             break;
  184.         
  185.         case kReadInterruptPipe:
  186.             InitParamBlock(pMousePB->pipeRef, &pMousePB->pb);
  187.  
  188.             pMousePB->pb.usbBuffer = (Ptr)pMousePB->hidReport;
  189.             pMousePB->pb.usbReqCount = pMousePB->maxPacketSize;
  190.             pMousePB->pb.usb.cntl.WIndex = pMousePB->interfaceDescriptor.interfaceNumber;    
  191.             
  192.             pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
  193.             pMousePB->pb.usbRefcon |= kCompletionPending;
  194.         
  195.             myErr = USBIntRead(&pMousePB->pb);
  196.             if(immediateError(myErr))
  197.             {
  198.                 USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": Read Interrupt Pipe (ImmediateError)", myErr);
  199.             }
  200.             break;
  201.             
  202.         default:
  203.             USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": Transaction initiated with bad refcon value", pMousePB->pb.usbRefcon);
  204.             pMousePB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  205.             break;
  206.     }
  207.     
  208. // At this point the control is returned to the system.  If a USB transaction
  209. // has been initiated, then it will call the Complete procs
  210. // (below) to handle the results of the transaction.
  211. }
  212.  
  213. void WatchDogCompletionProc(USBPB *pb)
  214. {
  215. usbMousePBStruct *pWatchDogPB;
  216. OSStatus myErr;
  217. UInt32    delayTime = 0;
  218.  
  219.     pWatchDogPB = (usbMousePBStruct *)(pb);
  220.     if (!pWatchDogPB->driverRemovalPending)
  221.     {
  222.         delayTime = 50;        // come back in 50ms if we're currently processing a completion callback
  223.         if (myMousePB.pb.usbRefcon & kCompletionInProgess)
  224.         {
  225.             USBExpertStatusLevel(5, pWatchDogPB->interfaceRef, kMouseModuleName": Watchdog occurred while processing a completion callback (check again in 50ms)", myMousePB.pb.usbRefcon);
  226.         }
  227.         else
  228.         {
  229.             switch(pWatchDogPB->watchDogState)
  230.             {
  231.                 case kDelay10Seconds:
  232.                     
  233.                     if (pWatchDogPB->watchDogActivityFlag)
  234.                     {
  235.                         USBExpertStatusLevel(5, pWatchDogPB->interfaceRef, kMouseModuleName": Watchdog - Mouse activity detected", pWatchDogPB->watchDogState);
  236.                         delayTime = 10000;
  237.                         pWatchDogPB->watchDogAbortFlag = false;
  238.                     }
  239.                     else
  240.                     {
  241.                         USBExpertStatusLevel(5, pWatchDogPB->interfaceRef, kMouseModuleName": Watchdog - No mouse activity detected, aborting pipe", pWatchDogPB->watchDogState);
  242.                         delayTime = 1000;
  243.                         pWatchDogPB->watchDogState = kCheckForAbort;
  244.                     }
  245.                     break;
  246.         
  247.                 case kCheckForAbort:
  248.                     delayTime = 10000;
  249.                     pWatchDogPB->watchDogState = kDelay10Seconds;
  250.                     
  251.                     if (pWatchDogPB->watchDogAbortFlag)
  252.                     {
  253.                         USBExpertStatusLevel(5, pWatchDogPB->interfaceRef, kMouseModuleName": Watchdog - Abort detected in completion routine", pWatchDogPB->watchDogState);
  254.                     }
  255.                     else
  256.                     {
  257.                         USBExpertStatusLevel(4, pWatchDogPB->interfaceRef, kMouseModuleName": Watchdog - No abort detected, restarting int read", pWatchDogPB->watchDogState);
  258.                         InitParamBlock(myMousePB.pipeRef, &myMousePB.pb);
  259.             
  260.                         myMousePB.pb.usbBuffer = (Ptr)myMousePB.hidReport;
  261.                         myMousePB.pb.usbReqCount = myMousePB.maxPacketSize;
  262.                         myMousePB.pb.usb.cntl.WIndex = myMousePB.interfaceDescriptor.interfaceNumber;    
  263.                         
  264.                         myMousePB.pb.usbCompletion = (USBCompletion)MouseCompletionProc;
  265.                         myMousePB.pb.usbRefcon = kReadInterruptPipe + kCompletionPending;
  266.                     
  267.                         myErr = USBIntRead(&myMousePB.pb);
  268.                         if(immediateError(myErr))
  269.                         {
  270.                             USBExpertFatalError(myMousePB.interfaceRef, kUSBInternalErr, kMouseModuleName": Watchdog - Read Interrupt Pipe (ImmediateError)", myErr);
  271.                         }
  272.                     }
  273.                     pWatchDogPB->watchDogAbortFlag = false;
  274.                     break;
  275.             }
  276.             pWatchDogPB->watchDogActivityFlag = false;
  277.             pWatchDogPB->watchDogAbortFlag = false;
  278.             if (pWatchDogPB->watchDogState == kCheckForAbort)
  279.             {
  280.                 USBAbortPipeByReference(pWatchDogPB->pipeRef);
  281.             }
  282.         }
  283.         InitParamBlock( pWatchDogPB->interfaceRef, &pWatchDogPB->pb );
  284.         
  285.         pWatchDogPB->pb.usbBuffer = 0;
  286.         pWatchDogPB->pb.usbActCount = 0;
  287.         pWatchDogPB->pb.usbReqCount = delayTime;            
  288.         
  289.         pWatchDogPB->pb.usbRefcon = 0;
  290.         pWatchDogPB->pb.usbCompletion = (USBCompletion)WatchDogCompletionProc;
  291.         
  292.         USBDelay(&pWatchDogPB->pb);
  293.         
  294.     }
  295.     return;
  296. }
  297.  
  298.  
  299. void MouseCompletionProc(USBPB *pb)
  300. {
  301. usbMousePBStruct     *pMousePB;
  302. unsigned char        * errstring;
  303. USBPipeState         pipeState;
  304.  
  305. #if EnableWatchDog
  306. OSStatus            myErr;
  307. #endif
  308.  
  309.     pMousePB = (usbMousePBStruct *)(pb);
  310.     pMousePB->transDepth--;
  311.     if (pMousePB->transDepth < 0)
  312.     {
  313.         USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": transDepth < 0 (completion)", pMousePB->pb.usbRefcon );
  314.     }
  315.     
  316.     if (pMousePB->transDepth > 1)
  317.     {
  318.         USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": transDepth > 1 (completion)", pMousePB->pb.usbRefcon );
  319.     }
  320.     
  321.     pMousePB->pb.usbRefcon |= kCompletionInProgess;                                            // make certain the watchdog routine doesn't race us
  322.     
  323.     if(pMousePB->pb.usbStatus != noErr)                                                        // was there an error?
  324.     {
  325.         switch(pMousePB->pb.usbRefcon & kStageMask)                                            // yes, so show where the error occurred
  326.         {
  327.             case kSetProtocol:                    errstring = kMouseModuleName": Error during kSetProtocol"; break;
  328.             case kSetIdleRequest:                  errstring = kMouseModuleName": Error during kSetIdleRequest"; break;
  329. #if EnableRemoteWakeup
  330.             case kSetRemoteWakeup:              errstring = kMouseModuleName": Error during kSetRemoteWakeup"; break;
  331. #endif
  332.             case kConfigureInterface:            errstring = kMouseModuleName": Error during kConfigureInterface"; break;
  333.             case kFindPipe:                      errstring = kMouseModuleName": Error during kFindPipe"; break;
  334.             case kReadInterruptPipe:
  335.                 {
  336.                 errstring = kMouseModuleName": Error during ReadInterruptPipe";
  337.                 LMSetMouseButtonState(0x80);    // release any possibly held-down mouse button
  338.                 break;
  339.                 }
  340.             default:                              errstring = kMouseModuleName": Error occurred, but state is unknown"; break;
  341.         };
  342.         
  343.         pMousePB->pb.usbRefcon &= (kStageMask + kCompletionInProgess);                        // save the refcon & completion in progress flag
  344.         pMousePB->pb.usbRefcon |= kRetryTransaction;                                        // set up to retry the transaction
  345.         pMousePB->retryCount--;
  346.         
  347.         // don't put out a fatal error message if an expected abort has occurred
  348.         if ((pMousePB->pb.usbStatus != kUSBAbortedError) || (watchDogPB.watchDogState != kCheckForAbort))
  349.         {
  350.             USBExpertFatalError(pMousePB->interfaceRef, pMousePB->pb.usbStatus, errstring, (pMousePB->pb.usbRefcon & kStageMask));
  351.         }
  352.         
  353.         if ((pMousePB->retryCount == 1) && ((pMousePB->pb.usbRefcon & kStageMask) == kSetIdleRequest))
  354.         {
  355.             USBExpertStatus(pMousePB->interfaceRef, kMouseModuleName": Device doesn't accept SetIdle", pMousePB->interfaceRef);
  356.             pMousePB->pb.usbRefcon = 
  357. #if EnableRemoteWakeup
  358.             kSetRemoteWakeup
  359. #else
  360.             kFindPipe
  361. #endif
  362.             ;
  363.             pMousePB->pb.usbStatus = noErr;
  364.         }
  365.         else
  366.         {
  367.             if ((pMousePB->pb.usbStatus == kUSBAbortedError) && (watchDogPB.watchDogState == kCheckForAbort))
  368.             {
  369.                 USBExpertStatusLevel(5, pMousePB->interfaceRef, kMouseModuleName": Expected abort has occurred - retry int read", pMousePB->interfaceRef);
  370.                 if (pMousePB->pipeRef)
  371.                 {    
  372.                         watchDogPB.watchDogAbortFlag = true;                                // flag that we had the abort
  373.                 }
  374.                 USBGetPipeStatusByReference(pMousePB->pipeRef, &pipeState);                    // yes, so what it's state?
  375.                 if (pipeState != kUSBActive)                                                // if it's not active, try to clear it.  It might be stalled...
  376.                 {
  377.                     USBExpertStatus(pMousePB->interfaceRef, kMouseModuleName": Pipe is open and stalled, clearing stall...", pMousePB->interfaceRef);
  378.                     USBClearPipeStallByReference(pMousePB->pipeRef);
  379.                 }
  380.             }
  381.             else if ((!pMousePB->retryCount) || (pMousePB->pb.usbStatus == kUSBAbortedError))    // have we exhausted the retries?
  382.             {                                                                                // or received an abort?
  383.                 USBExpertStatus(pMousePB->interfaceRef, kMouseModuleName": Pipe abort or unable to recover from error", pMousePB->interfaceRef);
  384.                 pMousePB->pb.usbRefcon = kReturnFromDriver + kCompletionInProgess;            // if so, just exit.
  385.                 pMousePB->intPipeAborted = true;    
  386.             }
  387.             else                                                                            // if it didn't abort and there's retries left, then...
  388.             {
  389.                 if (pMousePB->pipeRef)                                                        // check if the pipe is open.
  390.                 {
  391.                     USBGetPipeStatusByReference(pMousePB->pipeRef, &pipeState);                // yes, so what it's state?
  392.                     if (pipeState != kUSBActive)                                            // if it's not active, try to clear it.  It might be stalled...
  393.                     {
  394.                         USBExpertStatus(pMousePB->interfaceRef, kMouseModuleName": Pipe is open and stalled, clearing stall...", pMousePB->interfaceRef);
  395.                         USBClearPipeStallByReference(pMousePB->pipeRef);
  396.                     }
  397.                 }
  398.             }
  399.         }
  400.     }
  401.     else
  402.     {
  403.         pMousePB->pb.usbRefcon &= ~kRetryTransaction;
  404.         pMousePB->retryCount = kMouseRetryCount;
  405.     }
  406.  
  407.     if (pMousePB->pb.usbRefcon & kCompletionPending)             
  408.     {                                                
  409.         pMousePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  410.         switch(pMousePB->pb.usbRefcon & kStageMask)
  411.         {
  412.             case kConfigureInterface:
  413.                 pMousePB->pb.usbRefcon = kSetProtocol + kCompletionInProgess;
  414.                 break;
  415.                 
  416.             case kSetProtocol:
  417.                 if (kVendorID_AppleComputer == USBToHostWord(pMousePB->deviceDescriptor.vendor) )
  418.                 {
  419.                     pMousePB->pb.usbRefcon = 
  420. #if EnableRemoteWakeup
  421.                     kSetRemoteWakeup
  422. #else
  423.                     kFindPipe
  424. #endif
  425.                     + kCompletionInProgess;
  426.                 }
  427.                 else
  428.                 {
  429.                     pMousePB->pb.usbRefcon = kSetIdleRequest + kCompletionInProgess;
  430.                 }
  431.                 break;
  432.                 
  433.             case kSetIdleRequest:
  434.                 pMousePB->pb.usbRefcon = 
  435. #if EnableRemoteWakeup
  436.             kSetRemoteWakeup
  437. #else 
  438.             kFindPipe
  439. #endif
  440.                 + kCompletionInProgess;
  441.                 break;
  442.                 
  443. #if EnableRemoteWakeup
  444.             case kSetRemoteWakeup:
  445.                 pMousePB->pb.usbRefcon = kFindPipe;
  446.                 break;
  447. #endif
  448.                 
  449.             case kFindPipe:
  450.                 pMousePB->maxPacketSize = pMousePB->pb.usb.cntl.WValue;
  451.                 pMousePB->pipeRef = pMousePB->pb.usbReference;
  452.                 pMousePB->pb.usbRefcon = kReadInterruptPipe + kCompletionInProgess;
  453.  
  454.                 USBExpertStatus( watchDogPB.interfaceRef, kMouseModuleName": Initialize watchdog", 0);
  455.                 InitParamBlock( watchDogPB.interfaceRef, &watchDogPB.pb );
  456.                 
  457.                 watchDogPB.pipeRef = pMousePB->pipeRef;
  458.                 watchDogPB.watchDogState = kDelay10Seconds;
  459.                 
  460.                 watchDogPB.pb.usbBuffer = 0;
  461.                 watchDogPB.pb.usbActCount = 0;
  462.                 watchDogPB.pb.usbReqCount = 20000;            // check for mouse activity every twenty seconds
  463.                 watchDogPB.watchDogActivityFlag = false;
  464.                 
  465.                 watchDogPB.pb.usbRefcon =  0;
  466.                 watchDogPB.pb.usbCompletion = (USBCompletion)WatchDogCompletionProc;
  467.                 
  468.                 
  469. #if EnableWatchDog
  470.                 myErr = USBDelay(&watchDogPB.pb);
  471.                 if(immediateError(myErr))
  472.                 {
  473.                     USBExpertFatalError(pb->usbReference, myErr, kMouseModuleName": Setting up watchdog - USBDelay immediate error", 0);
  474.                 }
  475. #endif
  476.  
  477.                 break;
  478.                 
  479.             case kReadInterruptPipe:
  480.                 watchDogPB.watchDogActivityFlag = true;
  481.                 if (myMousePB.pNotificationRoutine)
  482.                 {
  483.                     (*myMousePB.pNotificationRoutine)(myMousePB.notificationRefcon, pMousePB->pb.usbActCount, (void *)pMousePB->hidReport, myMousePB.interfaceRef);
  484.                 }
  485.                 pMousePB->pb.usbRefcon = kReadInterruptPipe + kCompletionInProgess;
  486.                 break;
  487.  
  488.             default:
  489.                 USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": Transaction completed with bad refcon value", pMousePB->pb.usbRefcon );
  490.                 pMousePB->pb.usbRefcon = kUndefined + kReturnFromDriver + kCompletionInProgess;
  491.                 break;
  492.         }
  493.     }
  494.     
  495.     pMousePB->pb.usbRefcon &= ~(kCompletionInProgess);
  496.     if (!(pMousePB->pb.usbRefcon & kReturnFromDriver) && (!pMousePB->driverRemovalPending))
  497.         MouseInitiateTransaction(pb);
  498. }
  499.  
  500.  
  501. void InterfaceEntry(UInt32 interfacenum, USBInterfaceDescriptorPtr pInterfaceDescriptor, USBDeviceDescriptorPtr pDeviceDescriptor, USBReference theInterfaceRef)
  502. {
  503. #pragma unused (interfacenum)
  504.  
  505. static Boolean beenThereDoneThat = false;
  506.  
  507.     if(beenThereDoneThat)
  508.     {
  509.         USBExpertFatalError(theInterfaceRef, kUSBInternalErr, kMouseModuleName" is not reentrant", 0);
  510.         return;
  511.     }
  512.     beenThereDoneThat = true;
  513.     
  514.     // DebugStr("\pIn Mouse Interface Entry routine");
  515.  
  516.     watchDogPB.watchDogState = 0;
  517.     watchDogPB.watchDogAbortFlag = false;
  518.     watchDogPB.watchDogActivityFlag = false;
  519.     watchDogPB.driverRemovalPending = false;
  520.     watchDogPB.interfaceRef = theInterfaceRef;        
  521.     watchDogPB.pipeRef = nil;        
  522.     watchDogPB.pb.pbLength = sizeof(usbMousePBStruct);
  523.  
  524.     myMousePB.driverRemovalPending = false;
  525.     myMousePB.intPipeAborted = false;    
  526.  
  527.     myMousePB.deviceDescriptor = *pDeviceDescriptor;                
  528.     myMousePB.interfaceDescriptor = *pInterfaceDescriptor;            
  529.     
  530.     myMousePB.transDepth = 0;                            
  531.     myMousePB.retryCount = kMouseRetryCount;
  532.       
  533.     myMousePB.pSHIMInterruptRoutine = nil;
  534.     myMousePB.pSavedInterruptRoutine = nil;
  535.     
  536.     myMousePB.notificationRefcon = 0;
  537.     myMousePB.pNotificationRoutine = NotifyRegisteredHIDUser;
  538.  
  539.     myMousePB.interfaceRef = theInterfaceRef;        
  540.     myMousePB.pipeRef = nil;        
  541.     
  542.     InitParamBlock(theInterfaceRef, &myMousePB.pb);
  543.     
  544.     myMousePB.pb.usbReference = theInterfaceRef;
  545.     myMousePB.pb.pbLength = sizeof(usbMousePBStruct);
  546.     myMousePB.pb.usbRefcon = kConfigureInterface;        
  547.     
  548.     if ((myMousePB.deviceDescriptor.vendor == USB_CONSTANT16(0x046e)) &&
  549.         (myMousePB.deviceDescriptor.product == USB_CONSTANT16(0x6782)))
  550.     {
  551.         myMousePB.unitsPerInch = (Fixed)(100<<16);
  552.     }
  553.     else
  554.     {
  555.         myMousePB.unitsPerInch = (Fixed)(400<<16);
  556.     }
  557.     
  558.     myMousePB.pCursorDeviceInfo = 0;                
  559.     USBHIDControlDevice(kHIDEnableDemoMode,0);
  560.  
  561.     MouseInitiateTransaction(&myMousePB.pb);
  562. }
  563.  
  564.  
  565.  
  566.